﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GbmpQuickCast.h"

#include "IDocument.h"
#include "IGenericElement.h"


namespace gfam
{

    /// \brief 族对象转换工具函数
    class  FamilyElementUtils
    {

    public:

        /// \brief 获取T类型族对象
        /// 
        /// \param pDocument 文档
        /// \param id 对象id
        /// \return 成功返回族对象指针，否则返回nullptr
        template<class T>
        static  T* GetElement(const gcmp::IDocument* pDocument, gcmp::ElementId id)
        {
            static_assert(std::is_base_of<gcmp::IExternalObject, T>::value, "Family Element must derive from IExternalObject");

            if (gcmp::IGenericElement* pGenericElement = gcmp::quick_cast<gcmp::IGenericElement>(pDocument->GetElement(id)))
            {
                return gcmp::quick_cast<T>(pGenericElement->GetExternalObject());
            }

            return nullptr;
        }

        /// \brief 转换Element指针为T类型族对象指针
        /// 
        /// \param pElement Element指针
        /// \return 成功返回族对象指针，否则返回nullptr
        template<class T>
        static  T* CastElement(gcmp::IElement* pElement)
        {
            static_assert(std::is_base_of<gcmp::IExternalObject, T>::value, "Family Element must derive from IExternalObject");

            if (gcmp::IGenericElement* pGenericElement = gcmp::quick_cast<gcmp::IGenericElement>(pElement))
            {
                return gcmp::quick_cast<T>(pGenericElement->GetExternalObject());
            }

            return nullptr;
        }

        /// \brief 转换Element指针为T类型族对象指针
        /// 
        /// \param pElement Element指针
        /// \return 成功返回族对象指针，否则返回nullptr
        template<class T>
        static  const T* CastElement(const gcmp::IElement* pElement)
        {
            static_assert(std::is_base_of<gcmp::IExternalObject, T>::value, "Family Element must derive from IExternalObject");

            if (const gcmp::IGenericElement* pGenericElement = gcmp::quick_cast<gcmp::IGenericElement>(pElement))
            {
                return gcmp::quick_cast<T>(pGenericElement->GetExternalObject());
            }

            return nullptr;
        }

        /// \brief 判断一个Element是否是T类型族对象
        /// 
        /// \param pElement Element指针
        /// \return 是返回true，否则返回false
        template<class T>
        static bool IsA(const gcmp::IElement* pElement)
        {
            if (const gcmp::IGenericElement* pGenericElement = gcmp::quick_cast<gcmp::IGenericElement>(pElement))
            {
                return gcmp::quick_cast<const T>(pGenericElement->GetExternalObject()) != nullptr;
            }

            return false;
        }
    };

}